const fs = require('fs')
const path = require('path')
const usersProxy = require('../proxy/users')
const redisProxy = require('../common/redis')
const sms = require('../common/aliyun-sms')
const crypto = require('../common/crypto.api')
const validate = require('../common/validate')

exports.signUp = async function(req, res, next) {
  const phone = req.body.phone
  const code = await redisProxy.get(phone)
  if (!code || code !== req.body.code) {
    res.statusMessage = 'wrong code or it had been out-dated'
    res.status(227).end()
  } else {
    const salt = crypto.RandomNo()
    try {
      let { avatar } = req.body
      if (avatar) {
        const re = /data:image\/(ico|png|jpeg|jpg|gif);base64,(\S+)/
        avatar = new Buffer(req.body.avatar.replace(re, '$2'), 'base64')
      } else {
        avatar = fs.readFileSync(path.join(__dirname, '../static/avatars/avatar-' + Math.round(Math.random() * 10) + '.png'))
      }
      await usersProxy.createUser(
        salt,
        req.body.username,
        req.body.phone,
        crypto.Hash(req.body.password + req.body.username + salt),
        req.body.email || '',
        req.body.interests,
        avatar
      )
      res.json({ phone })
    } catch (err) {
      if (err.name === 'MongoError' && err.code === 11000) {
        res.statusMessage = 'phone has been registry'
        res.status(233).json({ phone })
      } else {
        next(err)
      }
    }
  }
}

exports.getVerificationCode = async function(req, res, next) {
  const phone = req.query.phone
  if (!validate.isPhone(phone)) {
    return res.status(400).json({ phone })
  }
  let code = await redisProxy.get(phone)
  console.log(`redis get code: ${code}`)
  if (code) {
    res.status(204).json({ phone })
  } else {
    code = Math.random().toString().slice(2, 8)
    console.log(`new code is: ${code}`)
    redisProxy.set(phone, code, 'EX', 60)
    /* comment below to save money*/
    sms.sendCode(phone, code)
      .then(function(res) {
        const { Code } = res
        if (Code === 'OK') {
          res.json({ phone })
        }
      }, function(err) {
        res.status(500).end()
      })
    res.json({ phone })
  }
}

exports.fetchUserInfo = async function(req, res, next) {
  try {
    const filterString = '-_id -contrast -current_party_stage -password -arancia -archive -followers'
    const user = await usersProxy.fetchUserById(req.params.userId).select(filterString)
    const data = {
      ...(user.toObject()),
      team: user.teams.length ? user.teams[0].team : ''
    }
    delete data.teams
    res.json(data)
  } catch (err) {
    res.status(500).end()
  }
}

exports.fetchUserRoles = async function(req, res, next) {
  res.json({ roles: req.user.roles })
}

exports.fetchUserFirstTeam = async function(userId) {
  try {
    const user = await usersProxy.fetchUserById(userId).select('teams')
    // console.log(user)
    if (user.teams.length === 0) return null
    else return user.teams[0]
  } catch (err) {
    return null
  }
}

exports.generateUserRoles = async(userId) => {
  try {
    const ac = await this.fetchUserFirstTeam(userId)
    if (!ac) return ['visitor']
    const roles = []
    if (ac.creator) roles.push('admin')
    else {
      const management = ['contrast', 'dormitory', 'bursary', 'evaluation', 'party', 'registry', 'vote', 'resource', 'announcement']
      for (const role of management) {
        if (ac.management[role]) roles.push(role)
      }
      if (roles.length === 0) roles.push('plain')
    }
    return roles
  } catch (err) {
    console.log(err.message)
    throw err
  }
}

exports.updateUserManagement = async function(userId, teamId) {
  try {
    const tags = await usersProxy.getAllTagsOfSbInTeam(userId, teamId)
    const keys = ['contrast', 'dormitory', 'bursary', 'evaluation', 'party', 'registry', 'vote', 'resource', 'announcement']
    const management = tags.reduce((total, current) => {
      for (const k of keys) {
        total[k] = total[k] || current[k]
      }
      return total
    }, {})
    await usersProxy.findOneAndUpdate({
      _id: userId, 'teams.team': teamId
    }, {
      'teams.$.management': management
    })
  } catch (err) {
    throw err
  }
}

exports.retrieve = async function(req, res, next) {
  const phone = req.body.phone
  const rawPassword = req.body.password
  const code = await redisProxy.get(phone)
  if (!validate.isPhone(phone)) {
    res.status(400).end()
  } else if (code === req.body.code) {
    try {
      const user = await usersProxy.fetchUserByPhone(phone).select('username arancia')
      if (!user) throw new Error('no exist phone')
      const password = crypto.Hash(rawPassword + user.username + user.arancia)
      await usersProxy.findOneAndUpdate({ _id: user.id }, { password })
      res.json({ phone })
    } catch (err) {
      res.status(404).end()
    }
  } else {
    res.status(227).end()
  }
}

exports.test = async(req, res, next) => {
  res.json({ hi: 'hello' })
  try {
    this.updateUserManagement()
  } catch (err) {
    console.log(err.message)
  }
  // if (req.session.view === undefined) {
  //   req.session.view = 0
  // } else {
  //   req.session.view++
  // }
  // console.log(req.query)
  // const user = await usersProxy.validateUserByPassword(req.query.p, req.query.pw)
  // res.json({ id: req.session.id, view: req.session.view, user })
}
